﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace CoordinateSystem.drawutils
{
    /// <summary>
    /// 坐标轴类型
    /// </summary>
    public enum AxisType { X=0,Y=1}

    /// <summary>
    /// 坐标系对象基础类
    /// </summary>
    public abstract class CoordinateBase
    {
        private int _Scale=30;
        private int _Margin=20;
        private int _Width=300;
        private int _Height=300;
       

        /// <summary>
        /// 刻度单位,每个刻度承载的像素数量
        /// </summary>
        public int Scale
        {
            get
            {
                return _Scale;
            }
            set
            {
                _Scale = value;
            }
        }

        /// <summary>
        /// 外补丁，与边界的距离单位为像素个数
        /// </summary>
        public int Margin
        {
            get
            {
                return _Margin;
            }
            set
            {
                _Margin = value;
            }
        }

        /// <summary>
        /// 整体宽度，单位为像素个数
        /// </summary>
        public int Width
        {
            get
            {
                return _Width;
            }
            set
            {
                _Width = value;
            }
        }

        /// <summary>
        /// 整体高度，单位为像素个数
        /// </summary>
        public int Height
        {
            get
            {
                return _Height;
            }
            set
            {
                _Height = value;
            }
        }

        /// <summary>
        /// 画布
        /// </summary>
        public Graphics Cavas { get; set; }

        /// <summary>
        /// 在画布上绘制图像
        /// </summary>
        public abstract void DrawObject();
        /// <summary>
        /// 取消绘制的图像
        /// </summary>
        public abstract void UndoDrawObject();

        public abstract void ResetCavas();
    }

    /// <summary>
    /// 坐标轴类
    /// </summary>
    public class Axis:CoordinateBase
    {
        private int _Max=0;
        private Font _TagFont;
        private Color _EraserColor;

        /// <summary>
        /// 名称
        /// </summary>
        public string Name 
        {
            get
            {
                return Atype.ToString();
            } 
        }

        public int Max
        {
            get
            {
                return _Max;
            }
            set
            {
                _Max = value;
            }
        }

        /// <summary>
        /// 标签字体
        /// </summary>
        public Font TagFont
        {
            get
            {
                return _TagFont;
            }
            set
            {
                _TagFont = value;
            }
        }

        /// <summary>
        /// 线条颜色
        /// </summary>
        public Color LineColor { get; set; } = Color.Black;

        public Color EraserColor
        {
            get
            {
                return _EraserColor;
            }
            set
            {
                _EraserColor = value;
            }
        }

        /// <summary>
        /// 线条宽度
        /// </summary>
        public int LineWidth { get; set; } = 2;

        /// <summary>
        /// 坐标轴类型
        /// </summary>
        public AxisType Atype { get; set; } = AxisType.X;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="at"></param>
        public Axis(AxisType at=AxisType.X)
        {
            Atype = at;
            _TagFont = new Font("宋体", 10);
        }
        /// <summary>
        /// 对象绘制内部方法
        /// </summary>
        /// <param name="lcolor">线条颜色</param>
        private void DrawInner(Color lcolor)
        {
            int x_center = (int)Math.Floor((double)(Width - Margin) / 2);
            int y_center = (int)Math.Floor((double)(Height - Margin) / 2);
            Point PointCenter = new Point(x_center, y_center);

            Pen pen = new Pen(lcolor, LineWidth);
            Brush bs = new SolidBrush(lcolor);

            // 横坐标轴
            if (Atype == AxisType.X)
            {
                _Max = (int)Math.Floor((double)x_center / Scale) - 1;
                // 绘制坐标线
                Point leftPoint = new Point((int)Margin, PointCenter.Y);
                Point rightPoint = new Point((int)Width - Margin, PointCenter.Y);
                Cavas.DrawLine(pen, leftPoint, rightPoint);
                // 绘制坐标箭头
                Point AendPoint = new Point((int)Width - Margin - LineWidth, PointCenter.Y);
                Point topA = new Point(AendPoint.X - 6, AendPoint.Y - 6);
                Point BottomA = new Point(AendPoint.X - 6, AendPoint.Y + 6);
                Cavas.DrawLine(pen, topA, AendPoint);
                Cavas.DrawLine(pen, BottomA, AendPoint);

                // 绘制刻度
                for (int i = 0; i <= _Max - 1; i++)
                {
                    int ind = i;
                    //正刻度横坐标
                    int g_x = x_center + (ind * Scale);
                    //负刻度横坐标
                    int l_x = x_center - (ind * Scale);

                    // 正刻度的起始及终端
                    Point t_g_point = new Point(g_x, y_center - LineWidth * 2);
                    Point g_point = new Point(g_x, y_center);
                    Cavas.DrawLine(pen, t_g_point, g_point);

                    //负刻度的起始及终端
                    Point l_g_point = new Point(l_x, y_center - LineWidth * 2);
                    Point l_point = new Point(l_x, y_center);
                    Cavas.DrawLine(pen, l_g_point, l_point);


                    //正负刻度的标记值
                    string g_tag = ind.ToString();
                    //位置相对刻度线向右下偏移两倍的线宽单位
                    Cavas.DrawString(g_tag, TagFont, bs, g_x + LineWidth * 2, y_center + LineWidth * 2);
                    string l_tag = (0 - ind).ToString();
                    Cavas.DrawString(l_tag, TagFont, bs, l_x + LineWidth * 2, y_center + LineWidth * 2);
                }
            }
            else if (Atype == AxisType.Y)
            {
                _Max = (int)Math.Floor((double)y_center / Scale) - 1;

                // 绘制坐标线
                Point bottomPoint = new Point(x_center, Height - Margin);
                Point topPoint = new Point((int)x_center, Margin);
                Cavas.DrawLine(pen, bottomPoint, topPoint);


                // 绘制箭头
                Point AendPoint = new Point((int)topPoint.X, topPoint.Y + 2);
                Point leftA = new Point(topPoint.X - 6, topPoint.Y + 6);
                Point rightA = new Point(topPoint.X + 6, topPoint.Y + 6);
                Cavas.DrawLine(pen, leftA, AendPoint);
                Cavas.DrawLine(pen, rightA, AendPoint);


                // 绘制刻度
                for (int i = 0; i < _Max; i++)
                {
                    int ind = i + 1;
                    //正刻度纵坐标
                    int g_y = y_center - (ind * Scale);
                    //负刻度纵坐标
                    int l_y = y_center + (ind * Scale);

                    // 正刻度的起始点及终点
                    Point r_g_point = new Point(x_center + LineWidth * 2, g_y);
                    Point g_point = new Point(x_center, g_y);
                    Cavas.DrawLine(pen, r_g_point, g_point);

                    //负刻度的起始及终端
                    Point l_g_point = new Point(x_center + LineWidth * 2, l_y);
                    Point l_point = new Point(x_center, l_y);
                    Cavas.DrawLine(pen, l_g_point, l_point);


                    //正负刻度的标记值
                    string g_tag = ind.ToString();
                    //位置相对刻度线向右上偏移两倍的线宽单位
                    Cavas.DrawString(g_tag, TagFont, bs, x_center + LineWidth * 2, g_y - LineWidth * 2);
                    string l_tag = (0 - ind).ToString();
                    Cavas.DrawString(l_tag, TagFont, bs, x_center + LineWidth * 2, l_y - LineWidth + 2);
                }
            }


        }

        /// <summary>
        /// 绘制对象
        /// </summary>
        public override void DrawObject()
        {
            DrawInner(LineColor);
        }

        public override void ResetCavas()
        {
            Cavas.Clear(EraserColor);
        }

        /// <summary>
        /// 取消绘制的对象
        /// </summary>
        public override void UndoDrawObject()
        {
            Pen pen = new Pen(EraserColor, LineWidth);
            DrawInner(EraserColor);
        }
    }
}
